#include "gfxServer.h"
#include "fileServer.h"
#include "eventServer.h"

using namespace sde;

GfxServer::GfxServer(std::string _type, std::string _name, Object* _object) :
    Action(_type,_name,_object),
    frameStart(0),
    frameCount(0) {
    if (setup())
        EventServer::getSingleton().subscribe("update",boost::bind(&GfxServer::update,this,_1));
    log("built %s %s",archetype.c_str(),type.c_str());
}

void GfxServer::update(VarMap args) {
    float time = boost::any_cast<float>(args["time"]);
    if (!frameCount) startTime = time;
//     if (time - frameStart > 0.016) {
        lastTime = time;
        ++frameCount;
        frameStart = time;
        root->renderOneFrame();
//     }
}

void GfxServer::stop() {
    log("graphics fps: %f",float(frameCount) / (lastTime - startTime));
}

bool GfxServer::setup() {
    root = new Ogre::Root(FileServer::getSingleton().getFileByName("plugins.cfg"),"gfx/ogre.cfg","gfx/ogre.log");
        
    setupResources();
    
    if (!configure()) {
        log("ERROR: failed to configure ogre");
        return false;
    }
    
    chooseSceneManager();
    createCamera();
    createViewports();
    
    Ogre::TextureManager::getSingleton().setDefaultNumMipmaps(5);
    
    loadResources();
    
    setupGui();
    
    return true;
}

bool GfxServer::configure() {
    if (root->restoreConfig() || root->showConfigDialog()) {
        window = root->initialise(true);
        return true;
    } else
        return false;
}

void GfxServer::chooseSceneManager() {
    sceneManager = root->createSceneManager(Ogre::ST_GENERIC, "SceneManager");
}

void GfxServer::createCamera() {
    camera = sceneManager->createCamera("Camera");
    camera->setPosition(Ogre::Vector3(0,100,150));
    camera->lookAt(Ogre::Vector3(0,0,0));
    camera->setNearClipDistance(5);
}

void GfxServer::createViewports() {
    Ogre::Viewport* vp = window->addViewport(camera);
    vp->setBackgroundColour(Ogre::ColourValue(0,0,0));
    camera->setAspectRatio(Ogre::Real(vp->getActualWidth()) / Ogre::Real(vp->getActualHeight()));
}

void GfxServer::setupResources() {
    StringList& folders = FileServer::getSingleton().folders;
    for (StringList::iterator i = folders.begin(); i != folders.end(); ++i)
        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(*i,"FileSystem");
        
    StringList zips = FileServer::getSingleton().getFilesByType("zip");
    for (StringList::iterator i = zips.begin(); i != zips.end(); ++i)
        Ogre::ResourceGroupManager::getSingleton().addResourceLocation(*i,"Zip");
}

void GfxServer::loadResources() {
    Ogre::ResourceGroupManager::getSingleton().initialiseAllResourceGroups();
}

Ogre::Vector3 GfxServer::VectorToOgreVector(Vector3 v) {
    return Ogre::Vector3(v.x,v.y,v.z);
}

Vector3 GfxServer::OgreVectorToVector(Ogre::Vector3 v) {
    return Vector3(v.x,v.y,v.z);
}

Ogre::Quaternion GfxServer::QuaternionToOgreQuaternion(Quaternion q) {
    return Ogre::Quaternion(q.w,q.x,q.y,q.z);
}

Quaternion GfxServer::OgreQuaternionToQuaternion(Ogre::Quaternion q) {
    return Quaternion(q.w,q.x,q.y,q.z);
}

void GfxServer::setupGui() {
    guiRenderer = new CEGUI::OgreCEGUIRenderer(window, Ogre::RENDER_QUEUE_OVERLAY, false, 3000, sceneManager);
    guiSystem = new CEGUI::System(guiRenderer);
    CEGUI::SchemeManager::getSingleton().loadScheme("TaharezLookSkin.scheme");
    guiWindowManager = CEGUI::WindowManager::getSingletonPtr();
    guiSheet = guiWindowManager->createWindow("DefaultGUISheet","Root");
    guiSystem->setGUISheet(guiSheet);
    CEGUI::MouseCursor::getSingleton().setImage(CEGUI::System::getSingleton().getDefaultMouseCursor());
}
